/*
 * Copyright 2021 Huawei Technologies Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// @Title  controllers
// @Description  Query and Delete api for filesystem
// @Author  GuoZhen Gao (2021/6/30 10:40)
package controllers

import (
	"encoding/json"
	"fileSystem/models"
	"fileSystem/util"
	log "github.com/sirupsen/logrus"
	"os"
)

// DownloadController   Define the Image controller to control query and delete
type ImageController struct {
	BaseController
}

// SlimInfo for developer
type CompressInfo struct {
	CompressStatus int     `json:"compressStatus"`
	CompressMsg    string  `json:"compressMsg"`
	CompressRate   float32 `json:"compressRate"`
}

type ImageBasicInfo struct {
	ImageId       string `json:"imageId"`
	FileName      string `json:"fileName"`
	UserId        string `json:"userId"`
	StorageMedium string `json:"storageMedium"`
	SaveFileName  string `json:"saveFileName"`
}

// @Title Get
// @Description perform local image query operation
// @Param	imageId 	string
// @Success 200 ok
// @Failure 400 bad request
// @router /image-management/v1/images/:imageId [GET]
func (c *ImageController) Get() {
	log.Info("Query for local image get request received.")

	var imageFileDb models.ImageDB

	imageId := c.Ctx.Input.Param(":imageId")

	if imageId == "" || len(imageId) == 0 {
		c.writeErrorResponse("fail to query database since the imageId is empty", util.StatusNotFound)
		return
	}

	log.Info("begin to query database with imageId:" + imageId)
	num, err := c.Db.QueryTable("image_d_b", &imageFileDb, "image_id__exact", imageId)

	if err != nil {
		log.Error("error status:" + err.Error())
		c.writeErrorResponse("query database with some err, the imageId is "+imageId, util.StatusNotFound)
		return
	}

	if num == 0 {
		c.writeErrorResponse("there is no record in database with imageId: "+imageId, util.StatusNotFound)
		return
	}

	filename := imageFileDb.FileName
	uploadTime := imageFileDb.UploadTime.Format("2006-01-02 15:04:05")
	userId := imageFileDb.UserId
	storageMedium := imageFileDb.StorageMedium

	slimStatus := imageFileDb.SlimStatus

	compressRate := imageFileDb.CompressRate
	compressMsg := imageFileDb.CompressMsg
	compressStatus := imageFileDb.CompressStatus

	var checkStatusResponse CheckStatusResponse
	var checkInfo CheckInfo
	var imageInfo ImageInfo
	var compressInfo CompressInfo

	if slimStatus == util.SlimmedSuccess {
		imageInfo.Filename = "compressed" + imageFileDb.SaveFileName
	} else {
		imageInfo.Filename = imageFileDb.SaveFileName
	}

	compressInfo.CompressStatus = compressStatus
	compressInfo.CompressMsg = compressMsg
	compressInfo.CompressRate = compressRate

	imageInfo.Format = imageFileDb.Format
	imageInfo.CheckErrors = imageFileDb.CheckErrors
	imageInfo.ImageEndOffset = imageFileDb.ImageEndOffset
	imageInfo.VirtualSize = imageFileDb.VirtualSize
	imageInfo.DiskSize = imageFileDb.DiskSize

	checkInfo.Checksum = imageFileDb.Checksum
	checkInfo.CheckResult = imageFileDb.CheckResult
	checkInfo.ImageInformation = imageInfo

	checkStatusResponse.Msg = imageFileDb.CheckMsg
	checkStatusResponse.Status = imageFileDb.CheckStatus
	checkStatusResponse.CheckInformation = checkInfo

	uploadResp, err := json.Marshal(map[string]interface{}{
		"imageId":             imageId,
		"fileName":            filename,
		"uploadTime":          uploadTime,
		"userId":              userId,
		"storageMedium":       storageMedium,
		"slimStatus":          slimStatus,
		"compressInfo":        compressInfo,
		"checkStatusResponse": checkStatusResponse,
	})

	if err != nil {
		c.writeErrorResponse("fail to return query details", util.StatusInternalServerError)
		return
	}

	_, _ = c.Ctx.ResponseWriter.Write(uploadResp)

}

// @Title Delete
// @Description perform local image delete operation
// @Param	imageId 	string
// @Success 200 ok
// @Failure 400 bad request
// @router /image-management/v1/images/:imageId [DELETE]
func (c *ImageController) Delete() {
	log.Info("Delete local image package request received.")

	var imageFileDb models.ImageDB

	imageId := c.Ctx.Input.Param(":imageId")

	_, err := c.Db.QueryTable("image_d_b", &imageFileDb, "image_id__exact", imageId)

	if err != nil {
		c.writeErrorResponse("fail to query this imageId in database", util.StatusNotFound)
		return
	}

	filename := imageFileDb.SaveFileName
	storageMedium := imageFileDb.StorageMedium

	file := storageMedium + filename
	err = os.Remove(file)

	if imageFileDb.SlimStatus == 2 {
		compressedFile := storageMedium + "compressed" + filename
		err = os.Remove(compressedFile)
	}

	fileRecord := &models.ImageDB{
		ImageId: imageId,
	}

	err = c.Db.DeleteData(fileRecord, "image_id")

	if err != nil && err.Error() != util.LastInsertIdNotSupported {
		c.writeErrorResponse("fail to delete package in db", util.StatusInternalServerError)
		return
	} else {
		c.Ctx.WriteString("delete success")
		log.Info("delete file from " + storageMedium)
	}
}
